package com.xyoto.community.service.impl;

import com.xyoto.community.cache.CacheInstruction;
import com.xyoto.community.cache.UserCache;
import com.xyoto.community.mapper.main.UserMapper;
import com.xyoto.community.service.UserCacheService;
import com.xyoto.community.utils.RedisCommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @author coderFu
 * @create 2021/11/7
 */
@Slf4j
@Service
public class UserCacheServiceImpl implements UserCacheService {

    private static final Object LOCK = new Object();
    @Autowired
    private RedisCommonUtils redisCommonUtils;

    @Autowired
    private UserMapper userMapper;



    @Override
    public UserCache getUserMessageFromUserCacheById(Integer userId) {
        if (userId == null){
            return null;
        }
        Object userObj = redisCommonUtils.hget(CacheInstruction.USER_CACHE, userId.toString());
        if (userObj == null) {
            //从数据库中获取用户信息
            Object userObj1 = redisCommonUtils.hget(CacheInstruction.USER_CACHE, userId.toString());
            if (userObj1 != null) {
                return (UserCache) userObj1;
            }
            return updateUserCacheMessage(userId);
        }
        return (UserCache) userObj;
    }

    public  UserCache updateUserCacheMessage(Integer userId) {
        Object userObj = redisCommonUtils.hget(CacheInstruction.USER_CACHE, userId.toString());
        if (userObj != null) {
            return (UserCache) userObj;
        }
        //从数据库中查询用户
        UserCache userCache = userMapper.getUserCache(userId);
        //存储到缓存中
        redisCommonUtils.hset(CacheInstruction.USER_CACHE, userCache.getId().toString(), userCache, CacheInstruction.USER_CACHE_EXPIRE_TIME);
        return userCache;
    }

    @Override
    @Async("taskExecutor")
    public synchronized void updateUserCache(UserCache userCache) {
        //更新用户的缓存信息, 前期使用直接更新的方式，
        // 后面可以使用延时双删，保证数据的高一致性
        redisCommonUtils.hset(CacheInstruction.USER_CACHE, userCache.getId().toString(), userCache, CacheInstruction.USER_CACHE_EXPIRE_TIME);
    }

    @Override
    public void deleteUserCache(Integer userId) {
        //删除用户的缓存信息
        redisCommonUtils.hdel(CacheInstruction.USER_CACHE,userId.toString());
    }

    @Override
    @Async("taskExecutor")
    public void addUserDynamicLoveStatus(Integer userId, Integer dynamicId) {
        //存储到缓存中
        redisCommonUtils.setBit(CacheInstruction.USER_DYNAMIC_LOVE+userId,dynamicId,true);
    }

    @Override
    @Async("taskExecutor")
    public void cancelUserDynamicLove(Integer userId, Integer dynamicId) {
        //取消用户点赞
        redisCommonUtils.setBit(CacheInstruction.USER_DYNAMIC_LOVE+userId,dynamicId,false);
    }

    @Override
    public boolean getUserDynamicLoveStatusFromCache(Integer userId, Integer dynamicId) {
        //从redis中获取点赞状态  ====》需要写一个一键同步点赞状态的方法
        return redisCommonUtils.getBit(CacheInstruction.USER_DYNAMIC_LOVE + userId, dynamicId);
    }

    @Override
    @Async("taskExecutor")
    public void addUserFollowStatus(Integer userId, Integer targetUserId) {
        //存储到redis
        redisCommonUtils.setBit(CacheInstruction.USER_FOLLOW+userId,targetUserId,true);
    }

    @Override
    @Async("taskExecutor")
    public void cancelUserFollow(Integer userId, Integer targetUserId) {
        //删除用户在缓存中的关注状态
        redisCommonUtils.setBit(CacheInstruction.USER_FOLLOW+userId,targetUserId,false);
    }

    @Override
    public boolean getUserFollowStatus(Integer userId, Integer targetUserId) {
        //获取用户的关注状态  ====》需要写一个一键同步关注状态的方法
        return redisCommonUtils.getBit(CacheInstruction.USER_FOLLOW + userId, targetUserId);

    }

    @Override
    @Async("taskExecutor")
    public void addUserAllDynamic(Integer userId, Integer dynamicId, long timestamp) {
        String key = CacheInstruction.USER_ALL_DYNAMIC +userId;
        //判断当前容器的大小是否超出最大的限度
        Long size = redisCommonUtils.getZsetSize(key);
        if (size >= CacheInstruction.MAX_COUNT_LIMIT) {
            //如果超出500条，那么实行先进先出原则,将最先进入的删除,默认是升序
            //剔除出第一条
            redisCommonUtils.removeFirstZSetValue(key);
        }
        //加入到缓存中
        redisCommonUtils.zSet(key, dynamicId, (double) timestamp);
    }

    @Override
    @Async("taskExecutor")
    public void deleteUserAllDynamicForMakePersonal(Integer userId, Integer dynamicId) {
        //移除缓存中的value
        String key = CacheInstruction.USER_ALL_DYNAMIC +userId;
        //判断是否存在
        boolean flag = redisCommonUtils.judgeZsetExistValue(key, dynamicId);
        if (flag){
            redisCommonUtils.removeZSetValue(key,dynamicId);
        }
    }

    @Override
    @Async("taskExecutor")
    public void deleteUserAllDynamicForDeleteDynamic(Integer userId, Integer dynamicId) {
        this.deleteUserAllDynamicForMakePersonal(userId,dynamicId);
    }

    @Override
    @Async("taskExecutor")
    public void recoverUserAllDynamic(Integer userId, Integer dynamicId, long timestamp) {
        this.addUserAllDynamic(userId,dynamicId,timestamp);
    }


}